#include "FloydWarshallTest.h"

namespace zbp
{
	using namespace boost;

double floyd_warshall_CompleteGraph_test(CompleteGraph<int> graph, bool display)
{
	/* initialization */
	DistanceMatrix<int> d = graph.distance_matrix;

	clock_t ticks = clock();

	graph.floyd_warshall(d);

	ticks = clock() - ticks;	
	double msec = (double)ticks / CLOCKS_PER_SEC * 1000;

	if (display)
	{
		cout << "CompleteGraph class: floyd_warshall method" << endl;
		d.display();
		cout << "Time in ms: " << msec << endl << endl;
	}

	return msec;
}

double floyd_warshall_initialized_CompleteGraph_test(CompleteGraph<int> graph, bool display)
{
	DistanceMatrix<int> d;

	clock_t ticks = clock();

	graph.floyd_warshall_initialized(d);

	ticks = clock() - ticks;	
	double msec = (double)ticks / CLOCKS_PER_SEC * 1000;

	if (display)
	{
		cout << "CompleteGraph class: floyd_warshall_initialized method" << endl;
		d.display();
		cout << "Time in ms: " << msec << endl << endl;
	}

	return msec;
}

double floyd_warshall_SimpleGraph_test(SimpleGraph graph, bool display)
{
	/* initialization */
	DistanceMatrix<int> d;
	graph.initialize_distance_matrix(d);

	clock_t ticks = clock();

	graph.floyd_warshall(d);

	ticks = clock() - ticks;	
	double msec = (double)ticks / CLOCKS_PER_SEC * 1000;

	if (display)
	{
		cout << "SimpleGraph class: floyd_warshall method" << endl;
		d.display();
		cout << "Time in ms: " << msec << endl << endl;
	}

	return msec;
}

double floyd_warshall_initialized_SimpleGraph_test(SimpleGraph graph, bool display)
{
	DistanceMatrix<int> d;

	clock_t ticks = clock();

	graph.floyd_warshall_initialized(d);

	ticks = clock() - ticks;	
	double msec = (double)ticks / CLOCKS_PER_SEC * 1000;

	if (display)
	{
		cout << "SimpleGraph class: floyd_warshall_initialized method" << endl;
		d.display();
		cout << "Time in ms: " << msec << endl << endl;
	}

	return msec;
}

double floyd_warshall_boost_test(BoostEdge* edge_array, int *weights, int nodes_count, int edges_count, bool display)
{
	typedef adjacency_list<vecS, vecS, directedS, no_property,
	property< edge_weight_t, int, property< edge_weight2_t, int > > > Graph;
	typedef std::pair < int, int >Edge;	
	
	#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
		// VC++ can't handle the iterator constructor
		Graph g(V);
		for (std::size_t j = 0; j < E; ++j)
		add_edge(edge_array[j].first, edge_array[j].second, g);
	#else
		Graph g(edge_array, edge_array + edges_count, nodes_count);
	#endif

	property_map < Graph, edge_weight_t >::type w = get(edge_weight, g);	
	graph_traits < Graph >::edge_iterator e, e_end;
	for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
	{
		w[*e] = *weights++;
	}

	std::vector < int >d(nodes_count, (std::numeric_limits < int >::max)());		
	int** D = new int*[nodes_count];
	for (int d = 0; d < nodes_count; d++)
	{
		D[d] = new int[nodes_count];
	}

	clock_t ticks = clock();

	bool result = boost::floyd_warshall_all_pairs_shortest_paths(g, D);

	ticks = clock() - ticks;	
	double msec = (double)ticks / CLOCKS_PER_SEC * 1000;

	if (display)
	{
		cout << "Boost: floyd_warshall_all_pairs_shortest_paths function" << endl;

		if (result)
			display_two_dim_array(D, nodes_count, std::numeric_limits<int>::max());
		else
			cout << "Negative cycle found." << endl;

		cout << "Time in ms: " << msec << endl << endl;
	}

	for (int i = 0; i < nodes_count; i++)
	{
		delete [] D[i];
	}
	delete[] D;

	return msec;
}

void floyd_warshall_tests_run(SimpleGraph simple_graph,
							  CompleteGraph<int> complete_graph,
							  BoostEdge* boost_edges, 
							  int* boost_weights,
							  int nodes_count, int edges_count)
{
	floyd_warshall_CompleteGraph_test(complete_graph, true);
	//floyd_warshall_initialized_CompleteGraph_test(complete_graph, true);
	floyd_warshall_SimpleGraph_test(simple_graph, true);
	//floyd_warshall_initialized_SimpleGraph_test(simple_graph, true);
	floyd_warshall_boost_test(boost_edges, boost_weights, nodes_count, edges_count, true);
}

}